﻿/*********************************************************************************
**                                                                              **
**  Copyright (C) 2024 LiLong                                                   **
**  This file is part of GnssLogs.                                              **
**                                                                              **
**  GnssLogs is free software: you can redistribute it and/or modify            **
**  it under the terms of the GNU Lesser General Public License as published by **
**  the Free Software Foundation, either version 3 of the License, or           **
**  (at your option) any later version.                                         **
**                                                                              **
**  GnssLogs is distributed in the hope that it will be useful,                 **
**  but WITHOUT ANY WARRANTY; without even the implied warranty of              **
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               **
**  GNU Lesser General Public License for more details.                         **
**                                                                              **
**  You should have received a copy of the GNU Lesser General Public License    **
**  along with GnssLogs.  If not, see <https://www.gnu.org/licenses/>.          **
**********************************************************************************/
#pragma once

#include "../TIME.h"
#include "LogHeaderDecoder.h"

namespace GnssLogs
{
namespace SBAS25Decoder
{
using namespace tao::pegtl;
using Sync   = TAO_PEGTL_STRING("#SBAS25A");
using Header = LogHeaderDecoder::SyncExpression<Sync>;
// clang-format off
struct PRN : star<digit> {};
struct HalfVel : star<digit> {};
struct HalfMask1 : star<digit> {};
struct HalfIode1 : star<digit> {};
struct HalfDx1 : seq<opt<one<'-'>>, star<digit>> {};
struct HalfDy1 : seq<opt<one<'-'>>, star<digit>> {};
struct HalfDz1 : seq<opt<one<'-'>>, star<digit>> {};
struct HalfAF0 : seq<opt<one<'-'>>, star<digit>> {};
struct HalfMask2 : star<digit> {};
struct HalfIode2 : star<digit> {};
struct HalfDDx : seq<opt<one<'-'>>, star<digit>> {};
struct HalfDDy : seq<opt<one<'-'>>, star<digit>> {};
struct HalfDDz : seq<opt<one<'-'>>, star<digit>> {};
struct HalfAF1 : seq<opt<one<'-'>>, star<digit>> {};
struct HalfT0 : star<digit> {};
struct HalfIODP : star<digit> {};
struct HalfCorrSpare : star<digit> {};
// clang-format on

using Half = seq<HalfVel,
                 Split,
                 HalfMask1,
                 Split,
                 HalfIode1,
                 Split,
                 HalfDx1,
                 Split,
                 HalfDy1,
                 Split,
                 HalfDz1,
                 Split,
                 HalfAF0,
                 Split,
                 HalfMask2,
                 Split,
                 HalfIode2,
                 Split,
                 HalfDDx,
                 Split,
                 HalfDDy,
                 Split,
                 HalfDDz,
                 Split,
                 HalfAF1,
                 Split,
                 HalfT0,
                 Split,
                 HalfIODP,
                 Split,
                 HalfCorrSpare>;

using Expression = seq<Header, PRN, Split, Half, Split, Half, one<'*'>, CRC32, Tail>;

template<typename T>
struct Action
{
};

template<>
struct Action<Header> : LogHeaderDecoder::LogHeaderHelperNoSetValue
{
};

template<>
struct Action<PRN> : IntHelper<Action<PRN>, uint32_t>
{
    inline static size_t halfIndex = 0;
    static void setValue(SBAS25::Data& data, uint32_t value)
    {
        halfIndex = 0;
        data.prn  = value;
    }
};

template<>
struct Action<HalfVel> : IntHelper<Action<HalfVel>, uint32_t>
{
    static void setValue(SBAS25::Data& data, uint32_t value) { data.halfs[Action<PRN>::halfIndex].halfVel = value; }
};

template<>
struct Action<HalfMask1> : IntHelper<Action<HalfMask1>, uint32_t>
{
    static void setValue(SBAS25::Data& data, uint32_t value) { data.halfs[Action<PRN>::halfIndex].halfMask1 = value; }
};

template<>
struct Action<HalfIode1> : IntHelper<Action<HalfIode1>, uint32_t>
{
    static void setValue(SBAS25::Data& data, uint32_t value) { data.halfs[Action<PRN>::halfIndex].halfIode1 = value; }
};

template<>
struct Action<HalfDx1> : IntHelper<Action<HalfDx1>, int32_t>
{
    static void setValue(SBAS25::Data& data, int32_t value) { data.halfs[Action<PRN>::halfIndex].halfDx1 = value; }
};

template<>
struct Action<HalfDy1> : IntHelper<Action<HalfDy1>, int32_t>
{
    static void setValue(SBAS25::Data& data, int32_t value) { data.halfs[Action<PRN>::halfIndex].halfDy1 = value; }
};

template<>
struct Action<HalfDz1> : IntHelper<Action<HalfDz1>, int32_t>
{
    static void setValue(SBAS25::Data& data, int32_t value) { data.halfs[Action<PRN>::halfIndex].halfDz1 = value; }
};

template<>
struct Action<HalfAF0> : IntHelper<Action<HalfAF0>, int32_t>
{
    static void setValue(SBAS25::Data& data, int32_t value) { data.halfs[Action<PRN>::halfIndex].halfAF0 = value; }
};

template<>
struct Action<HalfMask2> : IntHelper<Action<HalfMask2>, uint32_t>
{
    static void setValue(SBAS25::Data& data, uint32_t value) { data.halfs[Action<PRN>::halfIndex].halfMask2 = value; }
};

template<>
struct Action<HalfIode2> : IntHelper<Action<HalfIode2>, uint32_t>
{
    static void setValue(SBAS25::Data& data, uint32_t value) { data.halfs[Action<PRN>::halfIndex].halfIode2 = value; }
};

template<>
struct Action<HalfDDx> : IntHelper<Action<HalfDDx>, int32_t>
{
    static void setValue(SBAS25::Data& data, int32_t value) { data.halfs[Action<PRN>::halfIndex].halfDDx = value; }
};

template<>
struct Action<HalfDDy> : IntHelper<Action<HalfDDy>, int32_t>
{
    static void setValue(SBAS25::Data& data, int32_t value) { data.halfs[Action<PRN>::halfIndex].halfDDy = value; }
};

template<>
struct Action<HalfDDz> : IntHelper<Action<HalfDDz>, int32_t>
{
    static void setValue(SBAS25::Data& data, int32_t value) { data.halfs[Action<PRN>::halfIndex].halfDDz = value; }
};

template<>
struct Action<HalfAF1> : IntHelper<Action<HalfAF1>, int32_t>
{
    static void setValue(SBAS25::Data& data, int32_t value) { data.halfs[Action<PRN>::halfIndex].halfAF1 = value; }
};

template<>
struct Action<HalfT0> : IntHelper<Action<HalfT0>, uint32_t>
{
    static void setValue(SBAS25::Data& data, uint32_t value) { data.halfs[Action<PRN>::halfIndex].halfT0 = value; }
};

template<>
struct Action<HalfIODP> : IntHelper<Action<HalfIODP>, uint32_t>
{
    static void setValue(SBAS25::Data& data, uint32_t value) { data.halfs[Action<PRN>::halfIndex].halfIodp = value; }
};

template<>
struct Action<HalfCorrSpare> : IntHelper<Action<HalfCorrSpare>, uint32_t>
{
    static void setValue(SBAS25::Data& data, uint32_t value)
    {
        data.halfs[Action<PRN>::halfIndex].halfCorrSpare = value;
        Action<PRN>::halfIndex                           = 1;
    }
};

template<>
struct Action<CRC32> : CRC32Helper<Action<CRC32>>
{
    static void setValue(SBAS25::Data& data, uint32_t value) { data.crc32 = value; }
};
} // namespace SBAS25Decoder
} // namespace GnssLogs